package edu.isistan.matching.structures.elements;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

public class TypeElement extends WSDLElement {

	private boolean primitivo = false;
	private boolean anyType = false;

	protected List<TypeElement> subTiposList = new WsdlList<TypeElement>(this);
	private String nameSpace = "";
	private String type = "";
		
	/**
	 * Indica en nameSpace correspondiente al schema que contiene el elemento
	 * Este valor es util para obtener el nombre de paquete java asociado al elemento
	 */
	private String targetNameSpace = "";
	
	/**
	 * Indica si el elemento puede ser nulo, con lo cual si el elemento es primitivo
	 * la clase java correspondiente deberá ser un wrapper al tipo primitivo
	 */
	private boolean nillable = false;
	
	/**
	 * Indica si la instancia del elemento puede contener un conjunto de elementos del mismo tipo,
	 * con lo cual la clase java correspondiente debera ser un arreglo del tipo
	 */
	private boolean secuencia = false;
	
	private boolean lista = false;
	
	public TypeElement(String nombre) {
		super(nombre);
	}

	public boolean isPrimitivo() {
		return primitivo;
	}
	
	public boolean isSimpleType(){
		return false;
	}
	public void setPrimitivo(boolean primitivo) {
		this.primitivo = primitivo;
	}

	public List<TypeElement> getSubTiposList() {
		return subTiposList;
	}

	public void setSubTiposList(List<TypeElement> subTiposList) {
		this.subTiposList = subTiposList;
		if (subTiposList != null) {
			for (TypeElement element : subTiposList) {
				element.setParentElement(this);
			}
		}
	}

	public String toString() {
		return "[Type: " + getName() + ", nameSpace: " + getNameSpace() + " , Subtypes{" + getSubTiposList() + "}]";
	}

	public String getNameSpace() {
		return nameSpace;
	}

	public void setNameSpace(String nameSpace) {
		this.nameSpace = nameSpace;
	}

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}

	public static final Set<String> PRIMITIVE_TYPES = Collections.synchronizedSet(new HashSet<String>());
	static {
		PRIMITIVE_TYPES.add("byte");
		PRIMITIVE_TYPES.add("short");
		PRIMITIVE_TYPES.add("int");
		PRIMITIVE_TYPES.add("integer");
		PRIMITIVE_TYPES.add("unsignedByte");
		PRIMITIVE_TYPES.add("unsignedShort");
		PRIMITIVE_TYPES.add("unsignedInt");
		PRIMITIVE_TYPES.add("long");
		PRIMITIVE_TYPES.add("decimal");
		PRIMITIVE_TYPES.add("base64Binary");
		PRIMITIVE_TYPES.add("hexBinary");
		PRIMITIVE_TYPES.add("double");
		PRIMITIVE_TYPES.add("float");
		PRIMITIVE_TYPES.add("boolean");
		PRIMITIVE_TYPES.add("char");
		PRIMITIVE_TYPES.add("string");
		PRIMITIVE_TYPES.add("dateTime");
		PRIMITIVE_TYPES.add("date");
		PRIMITIVE_TYPES.add("time");
		PRIMITIVE_TYPES.add("QName");
		PRIMITIVE_TYPES.add("anySimpleType");
		PRIMITIVE_TYPES.add("Number");
	}
	public static String ANY_TYPE = "anyType";

	public boolean isAnyType() {
		return anyType;
	}

	public void setAnyType(boolean anyType) {
		this.anyType = anyType;
	}

	public String getTargetNameSpace() {
		return targetNameSpace;
	}

	public void setTargetNameSpace(String targetNameSpace) {
		this.targetNameSpace = targetNameSpace;
	}

	public boolean isNillable() {
		return nillable;
	}

	public void setNillable(boolean nillable) {
		this.nillable = nillable;
	}

	public boolean isSecuencia() {
		return secuencia;
	}

	public void setSecuencia(boolean secuencia) {
		this.secuencia = secuencia;
	}	
	
	public boolean isLista() {
		return lista;
	}

	public void setLista(boolean lista) {
		this.lista = lista;
	}
	@Override
	public Object clone() {
		TypeElement clone = new TypeElement(getName());
		clone.setAnyType(isAnyType());
		clone.setNameSpace(getNameSpace());
		clone.setNillable(isNillable());
		clone.setParentElement(getParentElement());
		clone.setPrimitivo(isPrimitivo());
		clone.setSecuencia(isSecuencia());
		clone.setTargetNameSpace(getTargetNameSpace());
		clone.setType(getType());
		List<TypeElement> list = new ArrayList<TypeElement>();
		for (Iterator iterator = getSubTiposList().iterator(); iterator.hasNext();) {
			TypeElement type = (TypeElement) iterator.next();
			list.add((TypeElement) type.clone());
		}
		clone.setSubTiposList(list);	
		return clone;
	}	
}